package output;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import forum.ForumItem;
import forum.ForumPost;
import forum.ForumSentence;
import forum.ForumTag;
import forum.ForumTopic;

public class QVXOutput extends DatabaseOutput {
	private OutputStream itemsOut;
	private OutputStream postOut;
	private OutputStream sentenceOut;
	private OutputStream sentenceitemOut;
	private OutputStream topicOut;
	private OutputStream tagPostOut;
	private OutputStream tagOut;
	private DataOutputStream dos; // uses bos, for ease of use
	private ByteArrayOutputStream bos; // buffer for writing

	public QVXOutput(String dir) throws IOException {
		for (File f : new File("corpus/qvxheaders").listFiles()) {
			File out = new File(dir + f.getName());
			if (f.getName().equals("item.qvx")) {
				itemsOut = setup(f, out);
			} else if (f.getName().equals("post.qvx")) {
				postOut = setup(f, out);
			} else if (f.getName().equals("sentence.qvx")) {
				sentenceOut = setup(f, out);
			} else if (f.getName().equals("sentenceitem.qvx")) {
				sentenceitemOut = setup(f, out);
			} else if (f.getName().equals("topic.qvx")) {
				topicOut = setup(f, out);
			} else if (f.getName().equals("tagpost.qvx")) {
				tagPostOut = setup(f, out);
			} else if (f.getName().equals("tag.qvx")) {
				tagOut = setup(f, out);
			} else
				throw new IOException("Unknown qvx-header file " + f.getName());
		}
		bos = new ByteArrayOutputStream();
		dos = new DataOutputStream(bos);
	}
	
	public void outputThread(List<ForumPost> f) throws Exception { 
		super.outputThread(f);
		flush();
	}

	private OutputStream setup(File f, File out) throws IOException {
		copy(f, out);
		OutputStream tmp = new FileOutputStream(out, true);
		return tmp;
	}
	
	private void flush() throws IOException {
		itemsOut.flush();
		postOut.flush();
		sentenceOut.flush();
		sentenceitemOut.flush();
		topicOut.flush();
		tagPostOut.flush();
		tagOut.flush();
	}

	@Override
	public void close() throws IOException {
		flush();
		itemsOut.close();
		postOut.close();
		sentenceOut.close();
		sentenceitemOut.close();
		topicOut.close();
		tagPostOut.close();
		tagOut.close();
	}

	// Copies src file to dst file.
	// If the dst file does not exist, it is created
	private void copy(File src, File dst) throws IOException {
		if (dst.exists())
			return;
		InputStream in = new FileInputStream(src);
		OutputStream out = new FileOutputStream(dst);

		// Transfer bytes from in to out
		byte[] buf = new byte[1024];
		int len;
		while ((len = in.read(buf)) > 0) {
			out.write(buf, 0, len);
		}
		out.write(0);
		in.close();
		out.close();
	}

	@Override
	public void insertSentence(ForumSentence sent) throws Exception {
		dos.writeInt(sent.getSentId());
		dos.writeUTF(sent.getText());
		dos.writeUTF(sent.getItemsText());
		dos.writeUTF(sent.getEmotion());
		dos.writeInt(sent.getPostId());
		bos.writeTo(sentenceOut);
		bos.reset();
	}

	@Override
	public void insertSentenceItem(ForumSentence sent, ForumItem item)
			throws Exception {
		dos.writeInt(sent.getSentId());
		dos.writeInt(item.getItemId());
		bos.writeTo(sentenceitemOut);
		bos.reset();
	}

	@Override
	public void insertPost(ForumPost post) throws Exception {
		dos.writeInt(post.getPostId());
		dos.writeUTF(post.getSource());
		dos.writeUTF(post.getPoster());
		dos.writeUTF(post.getPostDate());
		dos.writeUTF(post.getPostTime());
		dos.writeUTF(post.getTitle());
		dos.writeUTF(post.getHyperlink());
		dos.writeUTF(post.getForumCategory());
		bos.writeTo(postOut);
		bos.reset();
	}

	@Override
	public void insertItem(ForumItem item) throws Exception {
		dos.writeInt(item.getItemId());
		dos.writeUTF(item.getItemName());
		dos.writeInt(item.getTopic().getTopicId());
		bos.writeTo(itemsOut);
		bos.reset();
	}

	@Override
	public void insertTopic(ForumTopic topic) throws Exception {
		dos.writeInt(topic.getTopicId());
		dos.writeUTF(topic.getTopicName());
		bos.writeTo(topicOut);
		bos.reset();
	}

	@Override
	public void insertTag(ForumTag tag) throws Exception {
		dos.writeInt(tag.getTagId());
		dos.writeUTF(tag.getTagName());
		bos.writeTo(tagOut);
		bos.reset();
	}

	@Override
	public void insertTagsInPost(ForumPost post, ForumTag tag) throws Exception {
		dos.writeInt(post.getPostId());
		dos.writeInt(tag.getTagId());
		bos.writeTo(tagPostOut);
		bos.reset();
	}
}